package com.ccys.cms.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ccys.cms.controller.administrator.AccountController;
import com.ccys.cms.service.UserService;
import com.ccys.common.constants.ContextConstants;
import com.ccys.common.enums.CodeEnum;
import com.ccys.common.util.JedisUtil;
import com.ccys.common.util.Kit;
import com.ccys.common.vo.ResponseResult;
import com.ccys.db.cache.UserUtil;
import com.ccys.db.dto.administrator.ClinicSelectListDTO;
import com.ccys.db.entity.TblAccount;
import com.ccys.db.entity.TblAccountCountry;
import com.ccys.db.entity.TblPharmacy;
import com.ccys.db.mapper.*;
import com.ccys.db.page.PageDto;
import com.ccys.db.dto.web.base.SysUserDto;
import com.ccys.db.rely.service.impl.BaseServiceImpl;
import com.ccys.db.service.BaseTblAuditTrailWebService;
import com.ccys.db.vo.administrator.ClinicSelectListWebVO;
import com.ccys.db.vo.administrator.CompanySelectListWebVO;
import com.ccys.db.vo.administrator.PharmacySelectListWebVO;
import com.ccys.db.vo.administrator.TblSupportTabTitleWebVO;
import com.ccys.db.vo.web.base.AdminSelectVO;
import com.ccys.db.vo.web.base.AdminVo;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.ccys.common.vo.ResponseResult.error;
import static com.ccys.common.vo.ResponseResult.success;
import static com.ccys.common.vo.ResponseResult.update;


@Service
public class UserServiceImpl extends BaseServiceImpl<TblAccount> implements UserService {

	@Resource
	private TblAccountMapper accountMapper;

	@Resource
	private SysUserRoleMapper sysUserRoleMapper;
	@Resource
	private BaseTblAuditTrailWebService baseTblAuditTrailWebService;

	@Resource
	private TblCompanyMapper tblCompanyMapper;

	@Resource
	private TblClinicMapper tblClinicMapper;

    @Resource
    private TblPharmacyMapper tblPharmacyMapper;

	@Resource
	private TblAccountCountryMapper tblAccountCountryMapper;

	@Override
	public ResponseResult login( SysUserDto dto) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if (StringUtils.isEmpty(dto.getUserName()) || StringUtils.isEmpty(dto.getUserPassword())) {
			return error("parameter not passed");
		}
		// 查询当前账号是否存在
		List<String> whereList = new ArrayList<String>();
		whereList.add("user_name = '" + dto.getUserName() + "'");
		whereList.add("del_flag = '0'");//未删除
		TblAccount user = this.findOneByLimit(TblAccount.class, whereList);
		if (user == null) {
			return error("Account does not exist");
		}
		String md5Str = Kit.getPassword(dto.getUserPassword());
		// 判断账号密码
		if (!md5Str.equals(user.getUserPassword())) {
			TblAccount account = new TblAccount();
			int failedNum = user.getUserFailedPasswordCount() == null ? 0 : user.getUserFailedPasswordCount() + 1;
			account.setUserFailedPasswordCount(failedNum);
			if(failedNum >= 3) {
				//锁定账号  1  标识锁定
				account.setUserLoginStatus(1);
				account.setUserLastLockedOut(new Date());
			}
			this.updateEntityById(account);
			return error("Password error, account locked");
		}
		/**
		 * 判断登陆账号是否有登陆权限
		 */
		if (StringUtil.isEmpty(user.getUserType()) ) {
			return error("Account not authorized to log in");
		}
		if (!"dev".equals(user.getUserType()) && !"administrator".equals(user.getUserType()) && !"admin".equals(user.getUserType())) {
			return error("Account not authorized to log in");
		}
		// 判断是否被冻结
		if (0 == user.getUserStatus()) {
			return error("Account frozen");
		}


		String oldToken = JedisUtil.get(user.getId(), CodeEnum.REDIS_USER.codeOf());
		if(StringUtils.isNotEmpty(oldToken) && !"dev".equals(oldToken)){
			JedisUtil.del(oldToken, CodeEnum.REDIS_USER.codeOf());
			JedisUtil.del(user.getId(), CodeEnum.REDIS_USER.codeOf());
		}

		String token = Kit.getMD5Str(System.currentTimeMillis() + user.getUserName());
		JedisUtil.setexObj(token, ContextConstants.DEFAULT_NOT_OPERATED_TIME, JSONObject.toJSON(user), CodeEnum.REDIS_USER.codeOf());
		JedisUtil.setex(user.getId(),ContextConstants.DEFAULT_NOT_OPERATED_TIME, token, CodeEnum.REDIS_USER.codeOf());
		user.setToken(token);
		resultMap.put("user", user);
		TblAccount account = new TblAccount();
		account.setUserLastVisit(new  Date());
		this.updateEntityById(account);
		this.baseTblAuditTrailWebService.saveTblAuditTrail(account.getId(),account.getUserName(),3, JSON.toJSONString(dto),"tbl_account");
		return success(resultMap);
	}

	@Override
	@Transactional
	public ResponseResult exitLogin(HttpServletRequest request) {
		String token = request.getHeader("token");

		if (StringUtils.isNotEmpty(token)) {// 删除web端 登录缓存
			JedisUtil.del(token, CodeEnum.REDIS_USER.codeOf());
			JedisUtil.del(UserUtil.getCurLoginUserId(), CodeEnum.REDIS_USER.codeOf());
		}
		TblAccount curLoginAccount = UserUtil.getCurLoginAccount();
		if(curLoginAccount != null) {
			this.baseTblAuditTrailWebService.saveTblAuditTrail(curLoginAccount.getId(),curLoginAccount.getUserName(),4, JSON.toJSONString(curLoginAccount),"tbl_account");
		}
		return success();
	}

	@Override
	public ResponseResult queryAdmins( SysUserDto sysUserDto) {
		if(StringUtil.isEmpty(sysUserDto.getGroupId())) {
			sysUserDto.setGroupId(UserUtil.getCurLoginUserGroupId());
		}
		if(StringUtil.isEmpty(sysUserDto.getCompanyId())) {
			sysUserDto.setCompanyId(UserUtil.getCurLoginUserCompanyId());
		}
		if(StringUtil.isEmpty(sysUserDto.getClinicId())) {
			sysUserDto.setClinicId(UserUtil.getCurLoginUserClinicId());
		}
		if(StringUtil.isEmpty(sysUserDto.getPharmacyId())) {
			sysUserDto.setPharmacyId(UserUtil.getCurLoginUserPharmacyId());
		}
		if(StringUtil.isEmpty(sysUserDto.getCountryId())) {
			sysUserDto.setCountryId(UserUtil.getCurLoginUserCountryId());
		}

		PageDto.startPage();
		List<AdminVo> adminVos = accountMapper.queryAdmins(sysUserDto);
		PageInfo<AdminVo> info = new PageInfo<>(adminVos);
		return success(info);
	}

	@Override
	@Transactional
	public ResponseResult insertAdmin( SysUserDto sysUserDto) {
		TblAccount sysUser = new TblAccount();
		BeanUtils.copyProperties(sysUserDto,sysUser);
		sysUser.setUserStatus(1);
		sysUser.setUserLoginStatus(1);
		//设置默认密码
		sysUser.setUserPassword(Kit.getPassword(sysUser.getUserPassword()));
		sysUser.setUserType("admin");
		saveEntity(sysUser);
		String roleIds = sysUserDto.getRoleIds();
		if(StringUtil.isNotEmpty(sysUserDto.getCountryId())) {
			List<TblAccountCountry> list = new ArrayList<>();
			for (String s : sysUserDto.getCountryId().split(",")) {
				TblAccountCountry t = new TblAccountCountry();
				t.setAccountId(sysUser.getId());
				t.setCountryId(s);
				t.setCreatedOnUtc(System.currentTimeMillis());
				t.setCreatedBy(UserUtil.getCurLoginUserId());
				t.setId(IdUtil.randomUUID());
				t.setDelFlag(0);
				list.add(t);
			}
			this.tblAccountCountryMapper.insertList(list);
		}
		return update(sysUserRoleMapper.insertRelation(sysUser.getId(), Arrays.asList(roleIds.split(",")),sysUser.getCreatedBy()));
	}

	@Override
	@Transactional
	public ResponseResult updateAdmin( SysUserDto sysUserDto) {
		String roleIds = sysUserDto.getRoleIds();
		TblAccount sysUser = new TblAccount();
		BeanUtils.copyProperties(sysUserDto,sysUser);
		//密码加工
		if (StringUtils.isNotBlank(sysUser.getUserPassword())) {
            sysUser.setUserPassword(Kit.getPassword(sysUser.getUserPassword()));
        }
		if (StringUtils.isNotBlank(roleIds)) {
			sysUserRoleMapper.deleteRelation(sysUser.getId());
			sysUserRoleMapper.insertRelation(sysUser.getId(), Arrays.asList(roleIds.split(",")), sysUser.getCreatedBy());
		}
		if(sysUserDto.getUserStatus() != null) {
			this.baseTblAuditTrailWebService.saveStatusLog(sysUserDto,sysUserDto.getUserStatus());
		}
		if(sysUserDto.getUserLoginStatus() != null) {
			this.baseTblAuditTrailWebService.saveStatusLog(sysUserDto,sysUserDto.getUserLoginStatus());
		}
		if(StringUtil.isNotEmpty(sysUserDto.getCountryId())) {
			TblAccountCountry tblAccountCountry = new TblAccountCountry();
			tblAccountCountry.setAccountId(sysUser.getId());
			tblAccountCountryMapper.deleteByExample(tblAccountCountry);
			List<TblAccountCountry> list = new ArrayList<>();
			for (String s : sysUserDto.getCountryId().split(",")) {
				TblAccountCountry t = new TblAccountCountry();
				t.setAccountId(sysUser.getId());
				t.setCountryId(s);
				t.setCreatedOnUtc(System.currentTimeMillis());
				t.setCreatedBy(UserUtil.getCurLoginUserId());
				t.setId(IdUtil.randomUUID());
				t.setDelFlag(0);
				list.add(t);
			}
			this.tblAccountCountryMapper.insertList(list);
		}
		return update(updateEntityById(sysUser));
	}

	@Override
	public ResponseResult companySelectList(TblAccount dto) {
		//PageDto.startPage();
		List<CompanySelectListWebVO> list = this.tblCompanyMapper.companySelectList(dto);
		//PageInfo pageInfo = new PageInfo<>(list);
		return ResponseResult.success(list);
	}

	@Override
	public ResponseResult clinicSelectList(ClinicSelectListDTO dto) {
		PageDto.startPage();
		List<ClinicSelectListWebVO> list = this.tblClinicMapper.companySelectList(dto);
		PageInfo pageInfo = new PageInfo<>(list);
		return ResponseResult.success(pageInfo);
	}

    @Override
    public ResponseResult pharmacySelectList(TblAccount dto) {
        //PageDto.startPage();
        List<PharmacySelectListWebVO> list = this.tblPharmacyMapper.pharmacySelectList(dto);
        //PageInfo pageInfo = new PageInfo<>(list);
        return ResponseResult.success(list);
    }

	@Override
	public ResponseResult selectList(SysUserDto dto) {
		List<AdminSelectVO> list = this.accountMapper.selectList(dto);
		return ResponseResult.success(list);
	}
}
